package cn.wh.basic.service.impl;

import cn.wh.basic.constants.BaseConstant;
import cn.wh.basic.dto.RegisterDto;
import cn.wh.basic.exception.BusinessException;
import cn.wh.basic.service.IVerifyCodeSerivce;
import cn.wh.basic.util.StrUtils;
import cn.wh.basic.util.VerifyCodeUtils;
import cn.wh.user.domain.User;
import cn.wh.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * 注册发送验证码
 */
@Service
public class VerifyCodeSerivceImpl implements IVerifyCodeSerivce {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 发送图形验证码
     * @param key
     * @return
     */
    @Override
    public String imageCode(String key) {
        //
        if (!StringUtils.hasLength(key)){
            throw new BusinessException("不行,重试");
        }
        String code = StrUtils.getComplexRandomString(4);
        redisTemplate.opsForValue().set(
                key,
                code,
                5,
                TimeUnit.MINUTES
        );
        return VerifyCodeUtils.VerifyCode(100,38,code);
    }

    /**
     * 判断进入的是账号密码登录流程还是微信绑定流程
     * @param dto
     */
    @Override
    public void smsCode(RegisterDto dto) {
        String type = dto.getType();
        if(StringUtils.isEmpty(type)){
            throw new BusinessException("type业务类型不能为空");
        }
        if("register".equals(type)){//注册短信验证码
            registerSmsCode(dto);
        }else if("binder".equals(type)){//绑定短信验证码
            binderSmsCode(dto);
        }
    }

    /**
     * 微信绑定需要手机验证码
     * @param dto
     */
    private void binderSmsCode(RegisterDto dto) {
        String businessKey = BaseConstant.RegisterConstants.BINDER_SMS_PREFIX + dto.getPhone();
        //发送验证码逻辑
        sendSmsCode(businessKey);
    }


    /**
     * 账号密码登录需要的的业务---图形验证码+手机验证码
     * @param dto
     */
    public void registerSmsCode(RegisterDto dto) {
        String phone = dto.getPhone();
        String imageCodeKey = dto.getImageCodeKey();
        String imageCodeValue = dto.getImageCodeValue();
//          1.空校验
        if (StringUtils.isEmpty(phone)
                ||StringUtils.isEmpty(imageCodeKey)
                ||StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("你不填 我怎么给你注册");
        }
//          2.校验图形验证码，根据imageCodeKey从redis获取图形验证码
        Object imageCodeTmp = redisTemplate.opsForValue().get(imageCodeKey);
//          。获取不到 图形验证码过期，重新获取
        if (imageCodeTmp == null){
            throw new BusinessException("图形验证码过期,请重新输入");
        }
//           。获取到了，比对图形验证码是否正确
        if (!imageCodeTmp.toString().equalsIgnoreCase(imageCodeValue)){
//           - 不正确，提示输入图形验证码错误
            throw new BusinessException("图形验证码错误,请重新输入");
        }
//      - 正确，往下走
//      3.校验手机号是否注册过了
        User userTmp = userMapper.loadByPhone(phone);
//          。注册过了，滚去登录
        if (userTmp != null){
            throw new BusinessException("该号码已经注册过,请前往登录");
        }
        //根据手机号拼接key，register:17713803440，从redis获取曾今可能发送的短信验证码
        String businessKey = BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX + phone;
        //发送验证码逻辑
        sendSmsCode(businessKey);
////      。没有注册过，往下走
////      二：短信验证码逻辑
////      1.根据手机号拼接key，register:17713803440，从redis获取曾今可能发送的短信验证码
//        String key1 = "re:" + phone;
//        Object smsCodeTmp = redisTemplate.opsForValue().get(key1);//9527:
////      1.1 获取到了
//        String smsCode = "";
//        if(smsCodeTmp != null){
////          1.1.1 校验是否过了一分钟重发时间 value  9527:232468742341657213
//            Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);
////          。小于一分钟  哥屋恩
//            if(System.currentTimeMillis() - oldTime <= 60*1000){
//                throw new BusinessException("别来搞事,好好遵守法律");
//            }
////          。大于一分中 （还没有到3分钟，验证码还有效），
////          使用还没过期的验证码，刷新过期时间
//            smsCode = smsCodeTmp.toString().split(":")[0];//9527
//        }else{
////          1.2 获取不到
////          1.2.1.生成新的短信验证码
//            smsCode = StrUtils.getComplexRandomString(4);
//        }
////      .存储redis 设置一个过期时间
//        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
//        redisTemplate.opsForValue().set(
//                key1,
//                smsCodeValue,
//                3,
//                TimeUnit.MINUTES
//        );
////      4.发送短信
//        //SmsUtils.sendSms(phone,"亲，您的验证码是："+smsCode+"。请在3分钟内使用！！");
//        System.out.println("亲，您的验证码是：" + smsCode + "。请在3分钟内使用！！");
    }

    /**
     * 发送手机验证码业务 公共代码
     * @param businessKey  根据手机号拼接key，159:register，从redis获取曾今可能发送的短信验证码
     */
    private void sendSmsCode(String businessKey) {
        //        。没有注册过，往下走
//        二：短信验证码逻辑
//        1.根据手机号拼接key，159:register，从redis获取曾今可能发送的短信验证码
        String key = businessKey;
        Object smsCodeTmp = redisTemplate.opsForValue().get(key);//9527:232468742341657213
//        1.1 获取到了
        String smsCode = "";
        if(smsCodeTmp != null){
//        1.1.1 校验是否过了一分钟重发时间 value
            Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);
            if(System.currentTimeMillis() - oldTime <= 1*60*1000){
//        。小于一分钟  哥屋恩
                throw new BusinessException("使劲骂！！！");
            }
//        。大于一分中 （还没有到3分钟，验证码还有效），
//        使用还没过期的验证码，刷新过期时间
            smsCode = smsCodeTmp.toString().split(":")[0];//9527
        }else{
//        1.2 获取不到
//        1.2.1.生成新的短信验证码
            smsCode = StrUtils.getComplexRandomString(4);
        }
//        3.存储redis 设置一个过期时间
        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(
                key,
                smsCodeValue,
                3,
                TimeUnit.MINUTES
        );
//        4.发送短信
        //SmsUtils.sendSms(phone,"亲，您的验证码是："+smsCode+"。请在3分钟内使用！！");
        System.out.println("亲，您的验证码是：" + smsCode + "。请在3分钟内使用！！");
    }

}

